package org.summer.lawyer.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.lang.tree.Tree;
import cn.hutool.core.lang.tree.TreeUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.dynamic.datasource.annotation.DSTransactional;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.summer.common.core.exception.ServiceException;
import org.summer.common.core.utils.MapstructUtils;
import org.summer.common.core.utils.TreeBuildUtils;
import org.summer.common.mybatis.core.page.PageQuery;
import org.summer.common.mybatis.core.page.TableDataInfo;
import org.summer.lawyer.constant.SystemConstants;
import org.summer.lawyer.domain.Category;
import org.summer.lawyer.domain.vo.category.CategoryCreateVo;
import org.summer.lawyer.domain.vo.category.CategoryUpdateVo;
import org.summer.lawyer.domain.vo.category.CategoryVo;
import org.summer.lawyer.mapper.CategoryMapper;
import org.summer.lawyer.service.ICategoryService;
import org.summer.system.domain.bo.SysDictDataBo;
import org.summer.system.domain.vo.SysDictDataVo;
import org.summer.system.service.ISysDictDataService;

import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 *
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class CategoryServiceImpl extends ServiceImpl<CategoryMapper, Category> implements ICategoryService {


    private final ISysDictDataService sysDictDataService;

    @Override
    public TableDataInfo<CategoryVo> selectPage(CategoryVo vo, PageQuery pageQuery) {
        LambdaQueryWrapper<Category> queryWrapper = Wrappers.lambdaQuery();
        queryWrapper.eq(vo.getParentId() != null, Category::getParentId, vo.getParentId())
                .eq(StrUtil.isNotBlank(vo.getCategoryName()), Category::getCategoryName, vo.getCategoryName())
                .ge(Category::getCategoryLevel, 1);
//        if (StrUtil.isNotBlank(pageQuery.getOrderByColumn()) && "categorySort".equals(pageQuery.getOrderByColumn())) {
//            queryWrapper.orderByDesc(Category::getCategorySort);
//        } else {
//            queryWrapper.orderByDesc(Category::getCategoryId);
//        }
        queryWrapper.orderByDesc(Category::getCategorySort);
        if (PageQuery.DEFAULT_PAGE_SIZE == pageQuery.getPageSize()) {
            return TableDataInfo.build(baseMapper.selectVoList(queryWrapper));
        }
        Page<CategoryVo> page = baseMapper.selectVoPage(pageQuery.build(), queryWrapper);
        return TableDataInfo.build(page);
    }

    /**
     * 查询符合条件的商品分类列表
     *
     * @param vo 查询条件
     * @return 商品分类列表
     */
    @Override
    public List<CategoryVo> selectCategoryVoList(CategoryVo vo) {
        LambdaQueryWrapper<Category> lqw = buildQueryWrapper(vo);
        return baseMapper.selectVoList(lqw);
    }

    @Override
    public List<CategoryVo> selectAllCategoryVoList(CategoryVo vo) {
        SysDictDataBo dictDataBo = new SysDictDataBo();
        dictDataBo.setDictType(SystemConstants.SERVICE_CATEGORY);
        List<SysDictDataVo> dictDataVoList = sysDictDataService.selectDictDataList(dictDataBo);
        if (CollUtil.isEmpty(dictDataVoList)) {
            throw new ServiceException("服务主分类未找到");
        }
        List<CategoryVo> categoryVoList = this.selectCategoryVoList(vo);
        for (SysDictDataVo dictDataVo : dictDataVoList) {
            CategoryVo categoryVo = new CategoryVo();
            categoryVo.setCategoryId(Long.parseLong(dictDataVo.getDictValue()));
            categoryVo.setCategoryName(dictDataVo.getDictLabel());
            categoryVo.setParentId(0L);
            categoryVo.setCategorySort(dictDataVo.getDictSort());
            categoryVoList.add(categoryVo);
        }
        return categoryVoList;
    }

    @Override
    public List<CategoryVo> selectCategoryVoListByParentId(Long parentId) {
        List<CategoryVo> list = selectAllCategoryVoList(new CategoryVo());
        List<CategoryVo> outList = CollUtil.newArrayList();
        List<CategoryVo> categoryVos = list.stream().filter(item -> item.getParentId().equals(parentId) || Objects.equals(item.getCategoryId(), parentId))
                .peek(item -> {
                    outList.add(item);
                    if (!item.getCategoryId().equals(parentId)) {
                        //查找下级
                        getChildrenList(item, list, outList);
                    }
                }).toList();
        return outList;
    }

    private void getChildrenList(CategoryVo root, List<CategoryVo> categoryVos, List<CategoryVo> outList) {
        categoryVos.stream().filter(item -> {
            return Objects.equals(item.getParentId(), root.getCategoryId());
        }).peek(item -> {
            outList.add(item);
            if(!Objects.equals(item.getCategoryId(), root.getCategoryId())) {
                getChildrenList(item, categoryVos, outList);
            }
        }).collect(Collectors.toList());
    }

    @Override
    public List<CategoryVo> selectCategoryVoListChildByParentId(Long parentId) {
        return List.of();
    }

    @Override
    public List<Long> selectIdsByParentId(Long parentId) {
        List<CategoryVo> categoryVos = selectCategoryVoListByParentId(parentId);
        return categoryVos.stream().map(CategoryVo::getCategoryId).collect(Collectors.toList());
    }

    private LambdaQueryWrapper<Category> buildQueryWrapper(CategoryVo vo) {
        Map<String, Object> params = vo.getParams();
        LambdaQueryWrapper<Category> lqw = Wrappers.lambdaQuery();
        lqw.like(StrUtil.isNotBlank(vo.getCategoryName()), Category::getCategoryName, vo.getCategoryName());
        lqw.eq(vo.getParentId() != null, Category::getParentId, vo.getParentId());
        lqw.eq(vo.getCategoryLevel() != null, Category::getCategoryLevel, vo.getCategoryLevel());
        lqw.like(StrUtil.isNotBlank(vo.getCategoryPath()), Category::getCategoryPath, vo.getCategoryPath());
        lqw.like(StrUtil.isNotBlank(vo.getParentName()), Category::getParentName, vo.getParentName());
        return lqw;
    }


    @Override
    public void saveCategory(CategoryCreateVo vo) {
        Category category = new Category();
        MapstructUtils.convert(vo, category);
        category.setCategoryLevel(SystemConstants.DEFAULT_CATEGORY);
        baseMapper.insert(category);
    }

    @Override
    public void updateCategory(CategoryUpdateVo vo) {
        Category category = new Category();
        MapstructUtils.convert(vo, category);
        LambdaUpdateWrapper<Category> updateWrapper = Wrappers.lambdaUpdate();
        updateWrapper.eq(Category::getCategoryId, vo.getCategoryId());
        baseMapper.update(category, updateWrapper);
    }

    @DSTransactional(rollbackFor = Exception.class)
    @Override
    public void deleteCategoryByIds(Collection<Long> ids) {
        if (CollUtil.isEmpty(ids)) {
            throw new ServiceException("主键不能为空");
        }
        ids.forEach(id -> {
            baseMapper.deleteById(id);
        });

    }

    @Override
    public CategoryVo selectCategoryVoById(Long id) {
        return baseMapper.selectVoById(id);
    }

    @Override
    public List<Tree<Long>> buildCategoryTreeSelect(List<CategoryVo> categories) {
        if (CollUtil.isEmpty(categories)) {
            return CollUtil.newArrayList();
        }
        List<CategoryVo> parentList = categories.stream().filter(item -> item.getParentId().equals(0L)).toList();
        return TreeUtil.build(categories, parentList.getFirst().getParentId(), TreeBuildUtils.DEFAULT_CONFIG, (category, tree) -> {
            tree.setId(category.getCategoryId());
            tree.setName(category.getCategoryName());
            tree.setParentId(category.getParentId());
            tree.setWeight(category.getCategorySort());
        });
    }

    @Override
    public List<Tree<Long>> selectCategoryTreeList(CategoryVo vo) {
        List<CategoryVo> categoryVoList = selectAllCategoryVoList(vo);
        return buildCategoryTreeSelect(categoryVoList);
    }
}
